//+------------------------------------------------------------------+
//|                                              ValidHighLowFinder.mq5 |
//|                        Copyright 2025, MetaQuotes Software Corp. |
//|                                             https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2025, MetaQuotes Software Corp."
#property link      "https://www.mql5.com"
#property version   "1.00"

input int      MagicNumber = 88888;        // EA魔术棒
input int      LookbackBars = 500;         // 分析的K线数量
input double   PointThreshold = 5000;       // 有效高低点阈值(点)

// 结构体存储K线高低点信息
struct SBarInfo
{
   double   high;
   double   low;
   datetime time;
   int      index;
};

// 定义比较函数的类型
typedef int (*TCompareFunc)(const SBarInfo&, const SBarInfo&);

//+------------------------------------------------------------------+
//| 检查有效高点函数                                                  |
//+------------------------------------------------------------------+
bool IsValidHigh(const SBarInfo &bars[], int highIndex, int totalBars, double threshold)
{
   if(highIndex < 0 || highIndex >= totalBars) 
      return false;
      
   double highValue = bars[highIndex].high;
   bool leftFound = false;   // 向左（过去）找到低于高点的点
   bool rightFound = false;  // 向右（未来）找到低于高点的点
   
   // 向左检查（更早的K线，索引增加）
   for(int i = highIndex + 1; i < totalBars; i++)
   {
      if(bars[i].low < highValue - threshold)
      {
         leftFound = true;
         break;
      }
   }
   
   // 向右检查（更新的K线，索引减小）
   for(int i = highIndex - 1; i >= 0; i--)
   {
      if(bars[i].low < highValue - threshold)
      {
         rightFound = true;
         break;
      }
   }
   
   return (leftFound && rightFound);
}

//+------------------------------------------------------------------+
//| 检查有效低点函数                                                  |
//+------------------------------------------------------------------+
bool IsValidLow(const SBarInfo &bars[], int lowIndex, int totalBars, double threshold)
{
   if(lowIndex < 0 || lowIndex >= totalBars) 
      return false;
      
   double lowValue = bars[lowIndex].low;
   bool leftFound = false;   // 向左（过去）找到高于低点的点
   bool rightFound = false;  // 向右（未来）找到高于低点的点
   
   // 向左检查（更早的K线，索引增加）
   for(int i = lowIndex + 1; i < totalBars; i++)
   {
      if(bars[i].high > lowValue + threshold)
      {
         leftFound = true;
         break;
      }
   }
   
   // 向右检查（更新的K线，索引减小）
   for(int i = lowIndex - 1; i >= 0; i--)
   {
      if(bars[i].high > lowValue + threshold)
      {
         rightFound = true;
         break;
      }
   }
   
   return (leftFound && rightFound);
}

//+------------------------------------------------------------------+
//| 按高点值降序排序的比较函数                                        |
//+------------------------------------------------------------------+
int CompareHigh(const SBarInfo &a, const SBarInfo &b)
{
   if(a.high < b.high) return 1;   // 降序排序
   if(a.high > b.high) return -1;
   return 0;
}

//+------------------------------------------------------------------+
//| 按低点值升序排序的比较函数                                        |
//+------------------------------------------------------------------+
int CompareLow(const SBarInfo &a, const SBarInfo &b)
{
   if(a.low > b.low) return 1;   // 升序排序
   if(a.low < b.low) return -1;
   return 0;
}

//+------------------------------------------------------------------+
//| 自定义数组排序函数                                                |
//+------------------------------------------------------------------+
void SortArray(SBarInfo &array[], int count, TCompareFunc compare)
{
   for(int i = 0; i < count - 1; i++)
   {
      for(int j = 0; j < count - i - 1; j++)
      {
         if(compare(array[j], array[j + 1]) > 0)
         {
            // 交换元素
            SBarInfo temp = array[j];
            array[j] = array[j + 1];
            array[j + 1] = temp;
         }
      }
   }
}

//+------------------------------------------------------------------+
//| 主逻辑函数                                                        |
//+------------------------------------------------------------------+
void FindValidHighLow()
{
   // 只在每根K线开始时运行一次
   static datetime lastBarTime = 0;
   datetime currentBarTime = iTime(_Symbol, _Period, 0);
   if(lastBarTime == currentBarTime) 
      return;
   lastBarTime = currentBarTime;
   
   // 获取品种和周期
   string symbol = _Symbol;
   ENUM_TIMEFRAMES period = _Period;
   
   // 计算实际点数阈值
   double threshold = PointThreshold * _Point;
   Print("_Point=", _Point);
   // 准备K线数据数组
   SBarInfo bars[];
   ArrayResize(bars, LookbackBars);
   
   // 填充K线数据（索引0为最新K线）
   for(int i = 0; i < LookbackBars; i++)
   {
      bars[i].high = iHigh(symbol, period, i);
      bars[i].low = iLow(symbol, period, i);
      bars[i].time = iTime(symbol, period, i);
      bars[i].index = i;  // 保存原始索引
   }
   
   // 创建用于排序的副本
   SBarInfo sortedBars[];
   ArrayResize(sortedBars, LookbackBars);
   ArrayCopy(sortedBars, bars);
   
   // 按高点降序排序
   SortArray(sortedBars, LookbackBars, CompareHigh);
   
   // 检查有效高点
   bool validHighFound = false;
   for(int i = 0; i < LookbackBars; i++)
   {
      int originalIndex = sortedBars[i].index;
      if(IsValidHigh(bars, originalIndex, LookbackBars, threshold))
      {
         Print("有效最高点: 时间=", TimeToString(bars[originalIndex].time), 
               ", 数值=", DoubleToString(bars[originalIndex].high, _Digits));
         validHighFound = true;
         break;
      }
   }
   if(!validHighFound)
      Print("有效最高点无");
   
   // 重置排序数组
   ArrayCopy(sortedBars, bars);
   
   // 按低点升序排序
   SortArray(sortedBars, LookbackBars, CompareLow);
   
   // 检查有效低点
   bool validLowFound = false;
   for(int i = 0; i < LookbackBars; i++)
   {
      int originalIndex = sortedBars[i].index;
      if(IsValidLow(bars, originalIndex, LookbackBars, threshold))
      {
         Print("有效最低点: 时间=", TimeToString(bars[originalIndex].time), 
               ", 数值=", DoubleToString(bars[originalIndex].low, _Digits));
         validLowFound = true;
         break;
      }
   }
   if(!validLowFound)
      Print("有效最低点无");
}

//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick()
{
   FindValidHighLow();
}
//+------------------------------------------------------------------+
